#include <ut/UnitTest.h>
#include <illib/Log.h>
#include <illib/Buffer.h>
#include <illib/Exception.h>
#include <illib/System.h>

using namespace illib;
using namespace std;

namespace illib_ut{
	void Buffer_ut(){
		ut::UnitTestLogger logger(TN(ut::illib::Buffer_ut));
		ut::test(AT(), EX(MemoryTracker::tracker().empty()), TN(MemoryTracker::Tracker));
		{
			BlockAllocator::BasicAllocator allocator(1, 0);
			Buffer::Static b(allocator, 1000);
			b.destroy();

			Buffer::Static b1(0x00, 20);
			ut::test(AT(), EX(!b1.resize(b1.allocated(), true)), TN(Buffer::Static::resize));
			ut::test(AT(), EX(!b1.resize(b1.allocated()+1, true)), TN(Buffer::Static::resize));

		}
		ut::test(AT(), EX(MemoryTracker::tracker().empty()), TN(MemoryTracker::Tracker));
		{
			BlockAllocator::BasicAllocator allocator(1, 0);
			Buffer::Static b1(allocator, 1000);
			ut::test(AT(), EX(b1.resize(b1.allocated(), true)), TN(Buffer::Static::resize));
			MemoryTracker::Tracked * entry = MemoryTracker::tracker().entry(b1.start());
			ut::test(AT(), EX(entry != 0), TN(MemoryTracker::Tracker::entry));
			ut::test(AT(), EX(entry->allocator()), TN(Tracked::allocator));
			ut::test(AT(), EX(entry->allocator()->root() == &allocator), TN(Tracked::root));
			b1.destroy();

			Buffer::Static b2(allocator, 1000);
			ut::test(AT(), EX(b2.resize(b2.allocated()+1, true)), TN(Buffer::Static::resize));
			b2.destroy();

			Buffer::Static b3(allocator, 1000);
			entry = MemoryTracker::tracker().entry(b3.start());
			ut::test(AT(), EX(entry != 0), TN(MemoryTracker::Tracker::entry));
			ut::test(AT(), EX(entry->allocator()), TN(Tracked::allocator));
			ut::test(AT(), EX(entry->allocator()->root() == &allocator), TN(Tracked::root));
			b3.destroy();

			Buffer::Static b4(allocator, 10000);
			entry = MemoryTracker::tracker().entry(b4.start());
			ut::test(AT(), EX(entry != 0), TN(MemoryTracker::Tracker::entry));
			ut::test(AT(), EX(entry->allocator()), TN(Tracked::allocator));
			ut::test(AT(), EX(entry->allocator()->root() == &allocator), TN(Tracked::root));
			b4.destroy();

			Buffer::Static b5(allocator, 100000);
			entry = MemoryTracker::tracker().entry(b5.start());
			ut::test(AT(), EX(entry != 0), TN(MemoryTracker::Tracker::entry));
			ut::test(AT(), EX(entry->allocator()), TN(Tracked::allocator));
			ut::test(AT(), EX(entry->allocator()->root() == &allocator), TN(Tracked::root));
			b5.destroy();

			Buffer::Static b6(allocator, 1000000);
			entry = MemoryTracker::tracker().entry(b6.start());
			ut::test(AT(), EX(entry != 0), TN(MemoryTracker::Tracker::entry));
			ut::test(AT(), EX(entry->allocator()), TN(Tracked::allocator));
			ut::test(AT(), EX(entry->allocator()->root() == &allocator), TN(Tracked::root));
			b6.destroy();

		}
		ut::test(AT(), EX(MemoryTracker::tracker().empty()), TN(MemoryTracker::Tracker));
		{
			BlockAllocator::BasicAllocator allocator(1, 0);
			Buffer::Static b(allocator, 1000);
			b.resize(b.allocated(),true);
			b.resize(5000,true);
			b.resize(50000,true);
			b.resize(500000,true);
			b.resize(5000000,true);
			b.destroy();
		}
		ut::test(AT(), EX(MemoryTracker::tracker().empty()), TN(MemoryTracker::Tracker));
	}
};
